package dk.eclipse.android.badassapp.sensor.gyroscope;

import java.util.List;

import dk.eclipse.android.badassapp.sensor.SensorActivity;
import dk.eclipse.android.badassapp.sensor.pressure.PressureManager;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 */
public class GyroscopeManager {

	/** Accuracy configuration */
	private static float threshold = 0.2f;
	private static int interval = 1000;
	
	private static Sensor sensor;
	private static SensorManager sensorManager;

	private static GyroscopeListener listener;

	/** indicates whether or not the sensor is supported */
	private static Boolean supported;
	/** indicates whether or not the sensor is running */
	private static boolean running = false;

	/**
	 * Returns true if the manager is listening to changes
	 */
	public static boolean isListening() {
		return running;
	}

	/**
	 * Unregisters listeners
	 */
	public static void stopListening() {
		running = false;
		try {
			if (sensorManager != null && sensorEventListener != null) {
				sensorManager.unregisterListener(sensorEventListener);
			}
		} catch (Exception e) {
		}
	}

	/**
	 * Returns true if at least one sensor is available
	 */
	public static boolean isSupported() {
		Context context = SensorActivity.getContext();

		if (supported == null) {

			if (context != null) {
				sensorManager = (SensorManager) context
						.getSystemService(Context.SENSOR_SERVICE);
				List<Sensor> sensors = sensorManager
						.getSensorList(Sensor.TYPE_GYROSCOPE);
				supported = new Boolean(sensors.size() > 0);
			} else {
				supported = Boolean.FALSE;
			}
		}
		return supported;
	}

	/**
	 * Configure the listener for shaking
	 * 
	 * @param threshold
	 *            minimum acceleration variation for considering shaking
	 * @param interval
	 *            minimum interval between to shake events
	 */
	public static void configure(int threshold, int interval) {
		GyroscopeManager.threshold = threshold;
		GyroscopeManager.interval = interval;
	}


	/**
	 * Registers a listener and start listening
	 * 
	 * @param accelerometerListener
	 *            callback for events
	 */
	public static void startListening(
			GyroscopeListener accelerometerListener) {

		Context context = SensorActivity.getContext();

		sensorManager = (SensorManager) context
				.getSystemService(Context.SENSOR_SERVICE);
		List<Sensor> sensors = sensorManager
				.getSensorList(Sensor.TYPE_ACCELEROMETER);
		if (sensors.size() > 0) {
			sensor = sensors.get(0);
			running = sensorManager.registerListener(sensorEventListener,
					sensor, SensorManager.SENSOR_DELAY_GAME);
			listener = accelerometerListener;
		}
	}

	/**
	 * Configures threshold and interval And registers a listener and start
	 * listening
	 * 
	 * @param listener
	 *            callback for events
	 */
	public static void startListening(
			GyroscopeListener listener, int threshold,
			int interval) {
		configure(threshold, interval);
		startListening(listener);
	}

	/**
	 * The listener that listen to events from the listener
	 */
	private static SensorEventListener sensorEventListener = new SensorEventListener() {


		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}

		public void onSensorChanged(SensorEvent event) {

			float x = event.values[0];
			float y = event.values[1];
			float z = event.values[2];

			listener.onGyroscopeChanged(x, y, z);
		}

	};
}